/*
 * dwr_report.c

 *
 *  Created on: 10/05/2013
 *      Author: jose
 */

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#include <dbi/dbi.h>
#include "dwr_report.h"

#define MY_ENCODING "ISO-8859-1"


xmlChar *
ConvertInput(const char * in, const char *encoding)
{
    xmlChar * out;
    int ret;
    int size;
    int out_size;
    int temp;
    xmlCharEncodingHandlerPtr handler;

    if (in == 0)
        return 0;

    handler = xmlFindCharEncodingHandler(encoding);

    if (!handler) {
        printf("ConvertInput: no encoding handler found for '%s'\n",
               encoding ? encoding : "");
        return 0;
    }

    size = (int) strlen(in) + 1;
    out_size = size * 2 - 1;
    out = (unsigned char *) xmlMalloc((size_t) out_size);

    if (out != 0) {
        temp = size - 1;
        ret = handler->input(out, &out_size, (const xmlChar *) in, &temp);
        if ((ret < 0) || (temp - size + 1)) {
            if (ret < 0) {
                printf("ConvertInput: conversion wasn't successful.\n");
            } else {
                printf("ConvertInput: conversion wasn't successful. converted: %i octets.\n",
                     temp);
            }

            xmlFree(out);
            out = 0;
        } else {
            out = (unsigned char *) xmlRealloc(out, out_size + 1);
            out[out_size] = 0;  /*null terminating out */
        }
    } else {
        printf("ConvertInput: no mem\n");
    }

    return out;
}



/*
 * based on xmlWriter.c
 */
void
dwr_xml_write_doc(const unsigned char * file)
{
	assert(file);

	int drivercount, rc;
	char * ip = NULL, * url = NULL;
	unsigned port;
	unsigned long long ip_rows, url_rows, total_urls_rows;

    xmlTextWriterPtr writer;
    xmlChar *tmp;
    xmlDocPtr doc;

    dbi_conn db;
    dbi_result ip_result, url_result, total_urls_result;

    /* Instanciar libdbi y traer primer driver encontrado */
	drivercount = dbi_initialize(NULL);

	/* Setup para conectar a una DB postgres */
	db = dbi_conn_new("pgsql");
	dbi_conn_set_option(db, "host", "localhost");
	dbi_conn_set_option(db, "username", "postgres");
	dbi_conn_set_option(db, "password", "postgres");
	dbi_conn_set_option(db, "dbname", "dpiwebreports");

	/* Conectar a la DB */
	if (dbi_conn_connect(db) < 0)
		return;

	/* Ver cantidad de IPs origen en la BD */
	ip_result = dbi_conn_query(db, "select distinct(source_ip) as count_ip from packet");
	ip_rows = dbi_result_get_numrows(ip_result);

	if (!ip_result || !ip_rows)
		return;

    /* Create a new XmlWriter for DOM, with no compression. */
    writer = xmlNewTextWriterDoc(&doc, 0);
    if (writer == NULL)
    {
        printf("testXmlwriterDoc: Error creating the xml writer\n");
        return;
    }

    /* Start the document with the xml default for the version,
     * encoding ISO 8859-1 and the default for the standalone
     * declaration. */
    rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
    if (rc < 0)
    {
        printf("testXmlwriterDoc: Error at xmlTextWriterStartDocument\n");
        return;
    }

    /* Start an element named "dpireport". Since thist is the first
     * element, this will be the root element of the document. */
    rc = xmlTextWriterStartElement(writer, BAD_CAST "dpireport");
    if (rc < 0)
    {
        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
        return;
    }

    /* Write an element named "date" as child of dpireport. */
    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "date", "%s", "today");
    if (rc < 0)
    {
        printf("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
        return;
    }

    /* Start an element named "sessions" */
    rc = xmlTextWriterStartElement(writer, BAD_CAST "sessions");
    if (rc < 0)
    {
        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
        return;
    }

	/* Write an element named "len" as child of sessions */
	rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "len", "%llu", ip_rows);
	if (rc < 0) {
		printf("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
		return;
	}

	/* Obtener cantidad total de URLs distintas en la BD */
	total_urls_result = dbi_conn_query(db, "select distinct(http_host || http_resource) as total_urls from packet");
	if (!total_urls_result)
		return;

	total_urls_rows = dbi_result_get_numrows(total_urls_result);

	/* Write an element named "urls" as child of sessions */
	rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "urls", "%llu", total_urls_rows);
	if (rc < 0) {
		printf("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
		return;
	}

	/* Iterar sobre IPs */
	while (dbi_result_next_row(ip_result))
	{
		/* Start an element named "session" */
		rc = xmlTextWriterStartElement(writer, BAD_CAST "session");
		if (rc < 0) {
			printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
			return;
		}

		/* Obtener ip */
		ip = dbi_result_get_string(ip_result, "count_ip");

		/* Write an element named "ip" as child of session */
		rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ip", "%s", ip);
		if (rc < 0) {
			printf("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
			return;
		}

		/* Traer URLs correspondiente a la IP actual */
		url_result = dbi_conn_queryf(db,
						"select http_host || http_resource as url, dest_port from packet where source_ip='%s'",
						ip);

		if (url_result)
		{
			url_rows = dbi_result_get_numrows(url_result);

			/* Write an element named "len" as child of session */
			rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "len", "%llu", url_rows);

			while (dbi_result_next_row(url_result))
			{
				/* Start an element named "access" */
				rc = xmlTextWriterStartElement(writer, BAD_CAST "access");
				if (rc < 0)
				{
					printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
					return;
				}

				url = dbi_result_get_string(url_result, "url");
				/* Write an element named "url" as child of access */
				rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "url", "%s", url);

				/* Write an element named "timestamp" as child of access */
				rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "timestamp", "%s", "timestamp");
				port = dbi_result_get_uint(url_result, "dest_port");

				/* Write an element named "port" as child of access */
				rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "port", "%u", port);

				/* Finalizar un access */
				rc = xmlTextWriterEndElement(writer);
				if (rc < 0)
				{
					printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
					return;
				}

			}

			dbi_result_free(url_result);
		}

		/* Finalizar una sesión */
		rc = xmlTextWriterEndElement(writer);
		if (rc < 0)
		{
			printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
			return;
		}
	}

	dbi_result_free(ip_result);

    /* Close the element named sessions */
    rc = xmlTextWriterEndElement(writer);
    if (rc < 0)
    {
        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
        return;
    }

    /* Close the element named dpireport */
    rc = xmlTextWriterEndElement(writer);
    if (rc < 0)
    {
        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
        return;
    }

    xmlFreeTextWriter(writer);

    xmlSaveFileEnc(file, doc, MY_ENCODING);

    xmlFreeDoc(doc);
}
